package com.server.thisService.common.config;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
@Slf4j
@MapperScan(basePackages = "com.server.thisService.mapper", sqlSessionFactoryRef = "dataSqlSessionFactory")
public class DataDruidConfiguration {

    @Value("${spring.data.datasource.password}")
    private String jdbcPassword;

    @Value("${spring.data.datasource.url}")
    private String jdbcUrl;

    @Value("${spring.data.datasource.username}")
    private String jdbcUser;

    @Value("${spring.data.datasource.initial-size:5}")
    private int jdbcInitialSize;

    @Value("${spring.data.datasource.min-idle}")
    private int jdbcMinIdle;

    @Value("${spring.data.datasource.max-active}")
    private int jdbcMaxActive;

    // <!-- 配置获取连接等待超时的时间 -->
    @Value("${spring.data.datasource.max-wait}")
    private int jdbcMaxWait;

    //<!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 -->
    @Value("${spring.data.datasource.time-between-eviction-runs-millis:1000}")
    private int jdbcTimeBetweenEvictionRunsMillis;

    //<!-- 配置一个连接在池中最小生存的时间，单位是毫秒 -->
    @Value("${spring.data.datasource.min-evictable-idle-time-millis:30000}")
    private int jdbcMinEvictableIdleTimeMillis;

    @Value("${spring.data.datasource.validation-query}")
    private String jdbcValidationQuery;

    @Value("${spring.data.datasource.validation-query-timeout:2}")
    private int validationQueryTimeout;


    //连接闲时是否需要检测连接有效
    @Value("${spring.data.datasource.test-while-idle:true}")
    private boolean jdbcTestWhileIdle;

    //获取连接时是否需要检测连接有效
    @Value("${spring.data.datasource.test-on-borrow:false}")
    private boolean jdbcTestOnBorrow;

    //释放连接时是否需要检测连接有效
    @Value("${spring.data.datasource.test-on-return:false}")
    private boolean jdbcTestOnReturn;

    @Value("${spring.data.datasource.prepared-statements:true}")
    private boolean jdbcPoolPreparedStatements;

    //<!-- 打开PSCache，并且指定每个连接上PSCache的大小 -->
    @Value("${spring.data.datasource.max-pool-prepared-statement-per-connection-size:20}")
    private int jdbcMaxPoolPreparedStatementPerConnectionSize;

    //<!-- 配置监控统计拦截的filters -->
    @Value("${spring.data.datasource.filters:stat}")
    private String jdbcFilters = "stat";


    @Primary
    @Bean(name = "dataDruid")
    public DataSource dataSource() throws Exception {
        DruidDataSource ds = new DruidDataSource();
        try {
            ds.setUrl(jdbcUrl);
            ds.setUsername(jdbcUser);
            ResourceLoader resourceLoader = new DefaultResourceLoader();

            ds.setPassword(jdbcPassword);
            ds.setInitialSize(jdbcInitialSize);
            ds.setMinIdle(jdbcMinIdle);
            ds.setMaxActive(jdbcMaxActive);
            ds.setMaxWait(jdbcMaxWait);
            ds.setTimeBetweenEvictionRunsMillis(jdbcTimeBetweenEvictionRunsMillis);
            ds.setMinEvictableIdleTimeMillis(jdbcMinEvictableIdleTimeMillis);
            ds.setValidationQuery(jdbcValidationQuery);
            ds.setValidationQueryTimeout(validationQueryTimeout);
            ds.setTestWhileIdle(jdbcTestWhileIdle);
            ds.setTestOnBorrow(jdbcTestOnBorrow);
            ds.setTestOnReturn(jdbcTestOnReturn);
            ds.setPoolPreparedStatements(jdbcPoolPreparedStatements);
            ds.setMaxPoolPreparedStatementPerConnectionSize(
                    jdbcMaxPoolPreparedStatementPerConnectionSize);
            ds.setFilters(jdbcFilters);
        } catch (Exception e) {
            e.printStackTrace();
            if (null != ds && !ds.isClosed()) {
                ds.close();
            }
            throw new Exception("datasource construct failed", e);
        }

        return ds;
    }

    //注册事务管理器
    @Primary
    @Bean(name = "dataTransactionManager")
    public PlatformTransactionManager platformTransactionManager() throws Exception {
        return new DataSourceTransactionManager(dataSource());
    }

    //配置SqlSession工厂
    @Primary
    @Bean("dataSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        //指定数据源
        factoryBean.setDataSource(dataSource());
        //指定所有mapper.xml所在路径
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factoryBean.setMapperLocations(resolver.getResources("classpath:xml/*.xml"));
        factoryBean.setConfigLocation(resolver.getResources("classpath:config/mybatis-config.xml")[0]);
        return factoryBean.getObject();
    }

    @Primary
    @Bean(name = "dataSqlSessionTemplate")
    public SqlSessionTemplate financeSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
